//////////////////////////////////////////////////////////
//
//  This OPC server is built by using free version of Graybox OPC ToolKit
//  To register the OPC server type:
//    windopc -r
//  To remove the OPC server registration type:
//    windopc -u
//
//////////////////////////////////////////////////////////

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Graybox.OPC.ServerToolkit.CLRWrapper;

// Assembly attributes.
[assembly: AssemblyTitle("WindOPC")]
[assembly: AssemblyDescription("Wind Data OPC Server")]
[assembly: AssemblyCompany("Swinburne professional Project")]
[assembly: AssemblyProduct("Wind OPC Server")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.0")]

namespace WindOPC
{
    static class Program
    {
        // This int will be set to 1 when it's time to exit.
        static int stop = 0;
        // The TagId identifiers of OPC tags. There are two tags in the server
        static int[] tag_ids = new int[2];
        // The process entry point. Set [MTAThread] to enable free threading.
        // Free threading is required by the OPC Toolkit.
        [MTAThread]
        static void Main(string[] args)
        {
            // CLSID and the AppID of COM-object.
            Guid srv_guid = new Guid("5E20F035-0EA7-438F-BEA8-227BCC793716");
            // Command line args
            if (args.Length > 0)
            {
                try
                {
                    // Register the OPC server and return.
                    if (args[0].IndexOf("-r") != -1)
                    {
                        OPCDAServer.RegisterServer(
                            srv_guid,
                            "Wind Software",
                            "TestOPC",
                            "Swin.Project.WindOPC",
                            "1.0");
                        return;
                    }
                    // Remove the OPC server registration and return.
                    if (args[0].IndexOf("-u") != -1)
                    {
                        OPCDAServer.UnregisterServer(srv_guid);
                        return;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return;
                }
            }
            // Create an object of the OPC Server class.
            OPCDAServer srv = new OPCDAServer();
            // Add events handler for the OPC server.
            srv.Events.ServerReleased += new ServerReleasedEventHandler(Events_ServerReleased);
            // Initialize the OPC server object
            srv.Initialize(srv_guid, 50, 50, ServerOptions.NoAccessPaths, '.', 100);
            // Create the OPC tags.
            // Create wind speed tag.
            tag_ids[0] = srv.CreateTag(0, "Swin.WindSpeed", AccessRights.readable, 0);
            // Create wind direction tag.
            tag_ids[1] = srv.CreateTag(1, "Swin.WindDirection" , AccessRights.readable, "W");           
            // Mark the OPC server COM object as running.
            srv.RegisterClassObject();
            // Wait until the OPC server is released by the clients.
            
            // Update tags values while the OPC server is not released.
            while (System.Threading.Interlocked.CompareExchange(ref stop, 1, 1) == 0)
            {
                // Sleep for 10 seconds
                System.Threading.Thread.Sleep(10*1000);
                // Begin the update of the OPC server cache.
                srv.BeginUpdate();
                // Get current values of the two tags.
                object[] values = null;
                srv.GetTags(tag_ids, ref values);
                // Create a Bom object
                Bom WindData = new Bom();
                // Get HTML code of the website
                string html = WindData.getHTMLPage("http://www.bom.gov.au/products/IDV60801/IDV60801.94866.shtml");
                // Extract data from the HTML code
                string[] data = WindData.getWindData(html);
                // Update the tags value
                if (data[0] != null || data[1] != null)
                {
                    // Wind speed
                    srv.SetTag(tag_ids[0], Convert.ToInt32(data[0]), Quality.Good, FileTime.UtcNow);
                    // Wind direction
                    srv.SetTag(tag_ids[1], data[1], Quality.Good, FileTime.UtcNow);
                }              
                // Finish the update of the OPC server cache. We pass false,
                // because its unnecessary for this update to be synchronous.
                srv.EndUpdate(false);
            }
            // Mark the OPC server COM object as stopped.
            // Informs OLE that a class object,
            // previously registered with the RegisterClassObject function, is no longer available for use.
            srv.RevokeClassObject();
        }

        /// <summary>
        /// A handler for the ServerReleased event of the OPCDAServer object.
        /// </summary>
        static void Events_ServerReleased(object sender, ServerReleasedArgs e)
        {
            // Make the OPC server object 'suspended'.
            // No new OPC server instances can be created by the clients from this moment.
            e.Suspend = true;
            // Signal the main thread, that it's time to exit.
            System.Threading.Interlocked.Exchange(ref stop, 1);
        }



       
    }
}
